#include <math.h>
#include <stdio.h>

#include <QColor>
#include <QString>

#include "mainwindow.h"
#include "ui_mainwindow.h"

#include "Edge.h"
#include "Engine.h"

#define default_frame_width 20

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow) {

    ui->setupUi(this);
    scene = new QGraphicsScene();
    ui->H->setRange(10, 10000);
    ui->V0->setRange(10, 8000);
    ui->V1->setRange(10, 8000);
}

MainWindow::~MainWindow() {
    delete ui;
}

void MainWindow::resizeEvent(QResizeEvent * resize) {
    ui->plotView->setGeometry(QRect(0, 0,
                                   resize->size().width() - input_w - default_frame_width,
                                   resize->size().height() - default_frame_width) );
    ui->layoutWidget->setGeometry(QRect(resize->size().width() - input_w,
                                        resize->size().height() - input_h - default_frame_width,
                                        input_w,
                                        input_h) );
}

double ComputeTimeStep(double H, double V1, double V0) {
    return H / ((V0 - V1) * 40);
}

bool MainWindow::runPlot() {

    // Angle discretisation level.
    int ADL = ui->ADL->value();
    double H = ui->H->value();
    double V0 = ui->V0->value();
    double V1 = ui->V1->value();
    double timeStep = ComputeTimeStep(H, V1, V0);
    ui->timeStep->setText(QString::number(timeStep));


    if ((H <= 0) || (V0 <= 0) || (V1 < 0) || (ADL < 2) ||
            (timeStep <= 0)) {

        ui->statusbar->showMessage("Wrong input data");
        return false;
    }

    if (!wave) {

        wave = (struct Wave *) malloc(sizeof(struct Wave));
        wave->lines = (struct FrontLine *)malloc(sizeof(struct FrontLine) * ADL);
        wave->linesNumber = 0;
    }

    if (wave) {
        scene->clear();

        if (ADL > wave->linesNumber) {
            wave->lines = (struct FrontLine *)realloc(wave->lines, sizeof(struct FrontLine) * ADL);
        }

        for (int i = 0; i < ADL; i++) {

            (wave->lines + i)->vx = V0 * sin(M_PI * i / ADL);
            (wave->lines + i)->vy = V0 * cos(M_PI * i / ADL);
            (wave->lines + i)->x_current = 0.;
            (wave->lines + i)->y_current = 0.;
            (wave->lines + i)->x_prev = 0.;
            (wave->lines + i)->y_prev = 0.;
        }

        wave->V0 = V0;
        wave->V1 = V1;
        wave->height = H;
        wave->linesNumber = ADL;
        wave->timeStep = timeStep;
        wave->is_active = true;

        if (ADL < 30) {
            wave->next_visible_line = 1;

        } else {
            wave->next_visible_line = ADL / 15;
        }
    }

    runGraphics();
    return true;
}

bool MainWindow::runGraphics() {
    if (wave == 0) {
        return false;
    }

    if (wave->is_active == true) {
        while (FrontStep(wave) != 1) {

            for (int i = 0; i < wave->linesNumber; i++) {

                if (i != wave->linesNumber - 1) {

                    scene->addItem (new Edge((wave->lines + i)->x_current,
                                            (wave->lines + i)->y_current,
                                            (wave->lines + i + 1)->x_current,
                                            (wave->lines + i + 1)->y_current,
                                            Qt::black) );

                }

                if (i % wave->next_visible_line == 0 || i == wave->linesNumber - 1) {

                    scene->addItem (new Edge((wave->lines + i)->x_current,
                                            (wave->lines + i)->y_current,
                                            (wave->lines + i)->x_prev,
                                            (wave->lines + i)->y_prev,
                                            Qt::red) );
                }
            }
        }
    }
    ui->plotView->setScene(scene);
    return true;
}
